﻿using System;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Collections.Generic;
using System.Runtime.InteropServices;

using Job.Core.Common;
using Job.Core.Module;

namespace Job.Core.Security.Permissions
{
    /// <summary>
    /// 权限拦截。
    /// </summary>
    [Serializable]
    [ComVisible(true)]
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public sealed class PermissionAttribute : CodeAccessSecurityAttribute, IPermission, ICloneable
    {
        #region Properties
        
        private static readonly IPermissionHandler handler = ProviderService.GetModule("Permission") as IPermissionHandler;

        /// <summary>
        /// 获取权限模块处理程序。
        /// </summary>
        public static IPermissionHandler CurrentHandler
        {
            get
            {
                return handler;
            }
        }

        /// <summary>
        /// 功能。
        /// </summary>
        public string Function { get; set; }

        /// <summary>
        /// 操作。
        /// </summary>
        public string Operate { get; set; }

        /// <summary>
        /// 描述。
        /// </summary>
        public string Description { get; set; }

        #endregion

        #region Constructor

        /// <summary>
        /// 初始化 PermissionInterceptorAttribute 类的新实例。
        /// </summary>
        /// <param name="action">拦截方式。</param>
        private PermissionAttribute(SecurityAction action)
            : base(action)
        {
        }

        /// <summary>
        /// 初始化 PermissionInterceptorAttribute 类的新实例。
        /// </summary>
        /// <param name="interceptorAction">拦截方式。</param>
        public PermissionAttribute(InterceptorAction interceptorAction)
            : base((SecurityAction)interceptorAction)
        {

        }

        #endregion

        #region Methods

        /// <summary>
        /// 建立权限。
        /// </summary>
        /// <returns></returns>
        public override System.Security.IPermission CreatePermission()
        {
            return this;
        }

        /// <summary>
        /// 访问验证。
        /// </summary>
        public void Demand()
        {
            if (CurrentHandler != null && !CurrentHandler.IsAuthorize(Function, Operate))
                throw new SecurityException("您未被授权指定权限。");
        }

        /// <summary>
        /// 获取已加载程序集中所有权限特性。
        /// </summary>
        /// <param name="onlyWebApp">仅获取 Web 项目程序集。</param>
        /// <returns>权限数组。</returns>
        public static PermissionAttribute[] GetPermissions(bool onlyWebApp)
        {
            List<PermissionAttribute> list = new List<PermissionAttribute>();

            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assemblie in assemblies)
            {                
                //仅抓取动态编程的 Web 项目程序集。
                if (onlyWebApp && !assemblie.FullName.StartsWith("App_"))
                    continue;

                //忽略全局缓存的程序集。
                if (assemblie.GlobalAssemblyCache)
                    continue;

                Type[] types = assemblie.GetTypes();
                foreach (Type type in types)
                {
                    var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                    foreach (var method in methods)
                    {                        
                        object[] attrs = method.GetCustomAttributes(typeof(PermissionAttribute), false);
                        foreach (var attr in attrs)
                        {
                            PermissionAttribute per = (PermissionAttribute)attr;

                            //asp.net 动态生成dll时可能会存在多个，以下需确保唯一。
                            if (list.FirstOrDefault(item => item.Function == per.Function && item.Operate == per.Operate) == null)
                                list.Add(per);
                        }
                    }
                }
            }

            return list.ToArray();
        }

        #endregion

        #region IPermission 成员

        IPermission IPermission.Copy()
        {
            return (IPermission)Clone();
        }

        void IPermission.Demand()
        {            
            this.Demand();
        }

        IPermission IPermission.Intersect(IPermission target)
        {
            throw new NotImplementedException();
        }

        bool IPermission.IsSubsetOf(IPermission target)
        {
            throw new NotImplementedException();
        }

        IPermission IPermission.Union(IPermission target)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ISecurityEncodable 成员

        void ISecurityEncodable.FromXml(SecurityElement e)
        {
            throw new NotImplementedException();
        }

        SecurityElement ISecurityEncodable.ToXml()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            return ObjectFactory.Clone(this);
        }

        #endregion
    }

    /// <summary>
    /// 拦截类型。  
    /// </summary>
    [Serializable]
    public enum InterceptorAction
    {
        /// <summary>
        /// 请求访问。
        /// </summary>
        Demand = SecurityAction.Demand
    }
}